<?php
declare (strict_types=1);

namespace app;

use think\App;
use think\exception\ValidateException;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Request;
use think\Validate;

/**
 * 控制器基础类
 */
abstract class BaseController
{
    /**
     * Request实例
     * @var \think\Request
     */
    protected $request;

    /**
     * 应用实例
     * @var \think\App
     */
    protected $app;

    /**
     * 是否批量验证
     * @var bool
     */
    protected $batchValidate = false;

    /**
     * 控制器中间件
     * @var array
     */
    protected $middleware = [];

    /**
     * 构造方法
     * @access public
     * @param App $app 应用对象
     */
    public function __construct(App $app)
    {
        $this->app = $app;
        $this->request = $this->app->request;

        // 控制器初始化
        $this->initialize();
    }

    // 初始化
    protected function initialize()
    {
    }

    /**
     * 验证数据
     * @access protected
     * @param array $data 数据
     * @param string|array $validate 验证器名或者验证规则数组
     * @param array $message 提示信息
     * @param bool $batch 是否批量验证
     * @return array|string|true
     * @throws ValidateException
     */
    protected function validate(array $data, $validate, array $message = [], bool $batch = false)
    {
        if (is_array($validate)) {
            $v = new Validate();
            $v->rule($validate);
        } else {
            if (strpos($validate, '.')) {
                // 支持场景
                [$validate, $scene] = explode('.', $validate);
            }
            $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
            $v = new $class();
            if (!empty($scene)) {
                $v->scene($scene);
            }
        }

        $v->message($message);

        // 是否批量验证
        if ($batch || $this->batchValidate) {
            $v->batch(true);
        }

        return $v->failException(true)->check($data);
    }

    /**
     * 获取getStableAccessToken
     * @return mixed
     */
    public function getStableAccessToken()
    {
        //wxf625e9b4cee58c4f
        //66d8a08b9ae7e748b34acff5f99b9368
        $header = Request::header();
        $redis = Cache::store('redis')->handler();
        $redis->select(1);
        $accessToken = $redis->get('WxAccessToken');
        if (!$accessToken) {
            $partner = Db::name('partner')->where('type', '=', 1)->find();
            if ($partner) {
                $appId = $partner['app_id'];
                $appSecret = $partner['app_secret'];
                // 获取access_token
                $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appId . '&secret=' . $appSecret;

                $data = self::curlRequest($url, 'GET', '');

                $result = json_decode($data, true);
                if (empty($result['access_token'])) {

                    return $result;
                }
                Db::name('partner')->where('type', '=', 1)->update(['access_token' => $result['access_token'], 'expires_in' =>time() + 7200]);
                $accessToken = $result['access_token'];
                $redis->set('WxAccessToken', $accessToken, 7200);
            } else {
                return false;
            }
        }
        return $accessToken;
    }

    /**
     * 使用curl完成对接口的请求
     * @param $url :接口的url地址
     * @param string $type :传输类型,若为POST需要提供$data与$header
     * @param string $data :当type = POST时需要提供,为请求主体数据
     * @param array $header :当type = POST时需要提供,为请求头
     * @return bool|string
     */
    public static function curlRequest($url, string $type = 'POST', string $data = '')
    {
        $action = curl_init();
        curl_setopt($action, CURLOPT_URL, $url);
        curl_setopt($action, CURLOPT_CONNECTTIMEOUT, 60);
        curl_setopt($action, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($action, CURLOPT_HEADER, 0);
        curl_setopt($action, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($action, CURLOPT_SSL_VERIFYHOST, 0);
        if ($type == 'POST') {
            curl_setopt($action, CURLOPT_POST, 1);
            curl_setopt($action, CURLOPT_POSTFIELDS, $data);

            $header = array(
                "Content-Type: application/json; charset=UTF-8"
            );
            curl_setopt($action, CURLOPT_HTTPHEADER, $header);
        }
        $result = curl_exec($action);
        curl_close($action);
        return $result;
    }
}
